home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / SPLITTER.PAK / SPLITTER.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  12KB  |  467 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1995, 1996 by Borland International, All Rights Reserved
  4. //
  5. // $Revision:   10.8  $
  6. //
  7. // Sample illustrating ObjectWindows' Splitter Windows
  8. //----------------------------------------------------------------------------
  9. #include <owl/pch.h>
  10. #include <owl/decframe.h>
  11. #include <owl/applicat.h>
  12. #include <owl/inputdia.h>
  13. #include <owl/panespli.h>
  14. #include <owl/controlb.h>
  15. #include <owl/buttonga.h>
  16. #include <winsys/color.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include "splitter.rh"
  20.  
  21.  
  22. //----------------------------------------------------------------------------
  23.  
  24. const int MaxChildren = 50;
  25.  
  26. struct TChildInfo {
  27.   TWindow*  Child;
  28.   bool      CanClose;
  29.  
  30.   TChildInfo() {
  31.     Child = 0;
  32.     CanClose = true;
  33.   }
  34. };
  35.  
  36. TChildInfo  ChildInfo[MaxChildren+1];
  37.  
  38. //
  39. // class TMyChildWindow
  40. // ~~~~~ ~~~~~~~~~~~~~~
  41. class TMyChildWindow : public TWindow {
  42.   public:
  43.     TMyChildWindow(TWindow* parent, int id, char far* title);
  44.  
  45.   protected:
  46.     void  Paint(TDC&, bool, TRect&);
  47.  
  48.     void  EvLButtonDown(uint modKeys, TPoint& point) {
  49.       SetFocus();
  50.     }
  51.  
  52.     void EvSetFocus(THandle hWndLostFocus) {
  53.       Invalidate();
  54.       TWindow::EvSetFocus(hWndLostFocus);
  55.     }
  56.  
  57.     void EvKillFocus(THandle hWndGetFocus) {
  58.       Invalidate();
  59.       TWindow::EvKillFocus(hWndGetFocus);
  60.     }
  61.  
  62.     void CeCanClose(TCommandEnabler& ce) {
  63.       ce.Enable(!ChildInfo[GetId()].CanClose);
  64.     }
  65.  
  66.     void CmCanClose() {
  67.       ChildInfo[GetId()].CanClose = true;
  68.       Invalidate();
  69.     }
  70.  
  71.     void CeCantClose(TCommandEnabler& ce) {
  72.       ce.Enable(ChildInfo[GetId()].CanClose);
  73.     }
  74.  
  75.     void CmCantClose() {
  76.       ChildInfo[GetId()].CanClose = false;
  77.       Invalidate();
  78.     }
  79.  
  80.   DECLARE_RESPONSE_TABLE(TMyChildWindow);
  81. };
  82.  
  83. DEFINE_RESPONSE_TABLE1(TMyChildWindow, TWindow)
  84.   EV_WM_LBUTTONDOWN,
  85.   EV_WM_SETFOCUS,
  86.   EV_WM_KILLFOCUS,
  87.   EV_COMMAND       (CM_CANCLOSE, CmCanClose),
  88.   EV_COMMAND_ENABLE(CM_CANCLOSE, CeCanClose),
  89.   EV_COMMAND       (CM_CANTCLOSE, CmCantClose),
  90.   EV_COMMAND_ENABLE(CM_CANTCLOSE, CeCantClose),
  91. END_RESPONSE_TABLE;
  92.  
  93.  
  94. TMyChildWindow::TMyChildWindow(TWindow* parent, int id, char far* title)
  95.                :TWindow(parent, title)
  96. {
  97.   SetBkgndColor(TColor::SysWindow);
  98.   Attr.Style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS;
  99.   Attr.ExStyle = WS_EX_CLIENTEDGE;
  100.   Attr.Id = id;
  101. }
  102.  
  103. void
  104. TMyChildWindow::Paint(TDC& dc, bool, TRect&)
  105. {
  106.   char buf[20];
  107.   if (GetFocus() == GetHandle())
  108.     sprintf(buf, ">%d<", GetId());
  109.   else
  110.     sprintf(buf, " %d ", GetId());
  111.  
  112.   if (ChildInfo[GetId()].CanClose)
  113.     strcat(buf, " ");
  114.   else
  115.     strcat(buf, "x");
  116.   dc.TextOut(0, 0, buf);
  117. }
  118.  
  119. //----------------------------------------------------------------------------
  120.  
  121. //
  122. // class TMyPaneSplitter
  123. // ~~~~~ ~~~~~~~~~~~~~~~
  124. class TMyPaneSplitter : public TPaneSplitter {
  125.   public:
  126.     TMyPaneSplitter(TWindow* parent);
  127.  
  128.   protected:
  129.     void SetupWindow();
  130.     void InvalidPane(int num);
  131.  
  132.   private:
  133.     void CmMove();
  134.     void CmWidth();
  135.     void CmSplit();
  136.     void CmSplitVert();
  137.     void CmSplitHorz();
  138.     void CmShrink();
  139.     void CmGrow();
  140.     void CmRemove();
  141.     void CmReplace();
  142.     void CmSwap();
  143.     void CmForEachPane();
  144.     void CmSetSplitterWidth();
  145.     void CmNumberOfPanes();
  146.     void CmRemoveAllPanes();
  147.     void CmNewPaneClient(){ SplitPane(ChildInfo[0].Child, 0, psNone);}
  148.  
  149.     void CeMove(TCommandEnabler& ce){ce.Enable(PaneCount() > 0);};
  150.     void CeSplit(TCommandEnabler& ce){ce.Enable(PaneCount() > 0);};
  151.     void CeSplitVert(TCommandEnabler& ce){ce.Enable(PaneCount() > 0);};
  152.     void CeSplitHorz(TCommandEnabler& ce){ce.Enable(PaneCount() > 0);};
  153.     void CeShrink(TCommandEnabler& ce){ce.Enable(PaneCount() > 0);};
  154.     void CeGrow(TCommandEnabler& ce){ce.Enable(PaneCount() > 0);};
  155.     void CeRemove(TCommandEnabler& ce){ce.Enable(PaneCount() > 1);};
  156.     void CeReplace(TCommandEnabler& ce){ce.Enable(PaneCount() > 0);};
  157.     void CeSwap(TCommandEnabler& ce){ce.Enable(PaneCount() > 1);};
  158.     void CeNewPaneClient(TCommandEnabler& ce){ce.Enable(PaneCount() == 0);}
  159.  
  160.   DECLARE_RESPONSE_TABLE(TMyPaneSplitter);
  161. };
  162.  
  163. DEFINE_RESPONSE_TABLE1(TMyPaneSplitter, TPaneSplitter)
  164.   EV_COMMAND(CM_S_MOVE, CmMove),
  165.   EV_COMMAND(CM_S_WIDTH, CmWidth),
  166.   EV_COMMAND(CM_P_SPLIT, CmSplit),
  167.  
  168.   EV_COMMAND(CM_SPLITVERT, CmSplitVert),
  169.   EV_COMMAND(CM_SPLITHORZ, CmSplitHorz),
  170.   EV_COMMAND(CM_SHRINK, CmShrink),
  171.   EV_COMMAND(CM_GROW, CmGrow),
  172.  
  173.  
  174.   EV_COMMAND(CM_P_REMOVE, CmRemove),
  175.   EV_COMMAND(CM_P_REPLACE, CmReplace),
  176.   EV_COMMAND(CM_P_SWAP, CmSwap),
  177.   EV_COMMAND(CM_P_FOR_EACH_PANE, CmForEachPane),
  178.   EV_COMMAND(CM_S_SET_SPLITTER_WIDTH, CmSetSplitterWidth),
  179.   EV_COMMAND(CM_P_NUMBER_OF_PANES, CmNumberOfPanes),
  180.   EV_COMMAND(CM_P_REMOVE_ALL_PANES, CmRemoveAllPanes),
  181.   EV_COMMAND(CM_CREATEPANECLIENT, CmNewPaneClient),
  182.  
  183.   EV_COMMAND_ENABLE(CM_S_MOVE, CeMove),
  184.   EV_COMMAND_ENABLE(CM_P_SPLIT, CeSplit),
  185.  
  186.   EV_COMMAND_ENABLE(CM_SPLITVERT, CeSplitVert),
  187.   EV_COMMAND_ENABLE(CM_SPLITHORZ, CeSplitHorz),
  188.   EV_COMMAND_ENABLE(CM_SHRINK, CeShrink),
  189.   EV_COMMAND_ENABLE(CM_GROW, CeGrow),
  190.  
  191.   EV_COMMAND_ENABLE(CM_P_REMOVE, CeRemove),
  192.   EV_COMMAND_ENABLE(CM_P_REPLACE, CeReplace),
  193.   EV_COMMAND_ENABLE(CM_P_SWAP, CeSwap),
  194.  
  195.   EV_COMMAND_ENABLE(CM_CREATEPANECLIENT, CeNewPaneClient),
  196. END_RESPONSE_TABLE;
  197.  
  198. //
  199. //
  200. //
  201. TMyPaneSplitter::TMyPaneSplitter(TWindow* parent)
  202. :
  203.   TPaneSplitter(parent)
  204. {
  205.   Attr.Style |= WS_CLIPCHILDREN;
  206.   //
  207.   // Don't allow the separators to get any closer than 20 pixels.
  208.   // Prevents accidental closure of panes.
  209.   // 
  210.   SetSplitterCushion( 20 );
  211. }
  212.  
  213. void
  214. TMyPaneSplitter::InvalidPane(int num)
  215. {
  216.   char buff[50];
  217.   wsprintf(buff, "Index %d is not a valid pane");
  218.   MessageBox(buff, 0);
  219. }
  220.  
  221. void
  222. TMyPaneSplitter::CmMove()
  223. {
  224.   char buf[10] = "";
  225.   if (TInputDialog(GetApplication()->GetMainWindow(),
  226.                    "Move", "<pane #>, <distance>:",
  227.                    buf, sizeof(buf)).Execute() == IDOK) {
  228.     int pane = atoi(strtok(buf, ","));
  229.     int dist = atoi(strtok(0, ","));
  230.  
  231.     if (pane >= 0 && pane < MaxChildren) {
  232.       TWindow* child = ChildInfo[pane].Child;
  233.       if (child && child->GetHandle())
  234.         MoveSplitter(child, dist);
  235.       else
  236.         InvalidPane(pane);
  237.     }
  238.   }
  239. }
  240.  
  241. void
  242. TMyPaneSplitter::CmWidth()
  243. {
  244.   char buf[10] = "";
  245.  
  246.   itoa(GetSplitterWidth(), buf, 10);
  247.   MessageBox(buf, "Splitter Width", MB_OK);
  248. }
  249.  
  250. void
  251. TMyPaneSplitter::CmSplit()
  252. {
  253.   char buf[10] = "";
  254.   if (TInputDialog(GetApplication()->GetMainWindow(),
  255.                    "Split", "<Target Indx>,<New Indx>,<0=H|1=V>:",
  256.                    buf, sizeof buf).Execute() == IDOK) {
  257.     int w1 = atoi(strtok(buf, ","));
  258.     int w2 = atoi(strtok(0, ","));
  259.     int hv = atoi(strtok(0, ","));
  260.  
  261.     // NOTE: The two panes can be the same window
  262.     //       The first index must point to an existing pane
  263.     //       The second index must *NOT* point to an existing pane
  264.     //
  265.     if ((w1 != w2) &&
  266.         (ChildInfo[w1].Child->GetHandle() != 0) &&
  267.         (ChildInfo[w2].Child->GetHandle() == 0)) {
  268.       SplitPane(ChildInfo[w1].Child, ChildInfo[w2].Child,
  269.                 hv ? psVertical : psHorizontal);
  270.       ChildInfo[w1].Child->SetFocus();
  271.     }
  272.   }
  273. }
  274.  
  275. void
  276. TMyPaneSplitter::CmSplitVert()
  277. {
  278.   TWindow* curChild = GetWindowPtr(GetApplication()->GetMainWindow()->GetCommandTarget());
  279.   for (int i = 0; i < COUNTOF(ChildInfo); i++)
  280.     if (!ChildInfo[i].Child->GetHandle()) {
  281.       SplitPane(curChild, ChildInfo[i].Child, psVertical);
  282.       ChildInfo[i].Child->SetFocus();
  283.       return;
  284.     }
  285. }
  286.  
  287. void
  288. TMyPaneSplitter::CmSplitHorz()
  289. {
  290.   TWindow* curChild = GetWindowPtr(GetApplication()->GetMainWindow()->GetCommandTarget());
  291.   for (int i = 0; i < COUNTOF(ChildInfo); i++)
  292.     if (!ChildInfo[i].Child->GetHandle()) {
  293.       SplitPane(curChild, ChildInfo[i].Child, psHorizontal);
  294.       ChildInfo[i].Child->SetFocus();
  295.       return;
  296.     }
  297. }
  298.  
  299. void
  300. TMyPaneSplitter::CmShrink()
  301. {
  302.   TWindow* curChild = GetWindowPtr(GetApplication()->GetMainWindow()->GetCommandTarget());
  303.   if (curChild)
  304.     MoveSplitter(curChild, -2);
  305. }
  306.  
  307. void
  308. TMyPaneSplitter::CmGrow()
  309. {
  310.   TWindow* curChild = GetWindowPtr(GetApplication()->GetMainWindow()->GetCommandTarget());
  311.   if (curChild)
  312.     MoveSplitter(curChild, 2);
  313. }
  314.  
  315. void
  316. TMyPaneSplitter::CmRemove()
  317. {
  318.   char buf[10] = "";
  319.   if (TInputDialog(GetApplication()->GetMainWindow(),
  320.                    "Remove", "Window #:", buf, sizeof buf).Execute() == IDOK) {
  321.     int w1 = atoi(buf);
  322.     RemovePane(ChildInfo[w1].Child);
  323.   }
  324. }
  325.  
  326. void
  327. TMyPaneSplitter::CmReplace()
  328. {
  329.   char buf[10] = "";
  330.   if (TInputDialog(GetApplication()->GetMainWindow(),
  331.                    "Replace", "<Target pane index>,<New pane index>:",
  332.                    buf, sizeof buf).Execute() == IDOK) {
  333.     int w1 = atoi(strtok(buf, ","));
  334.     int w2 = atoi(strtok(0, ","));
  335.  
  336.     // First index must specify an existing pane while the second a
  337.     // brand new index..
  338.     //
  339.     if (ChildInfo[w1].Child->GetHandle() &&
  340.         !ChildInfo[w2].Child->GetHandle())
  341.       ReplacePane(ChildInfo[w1].Child, ChildInfo[w2].Child);
  342.   }
  343. }
  344.  
  345. void
  346. TMyPaneSplitter::CmSwap()
  347. {
  348.   char buf[10] = "";
  349.   if (TInputDialog(GetApplication()->GetMainWindow(),
  350.                    "Swap", "<Window1>,<Window2>:",
  351.                    buf, sizeof buf).Execute() == IDOK) {
  352.     int w1 = atoi(strtok(buf, ","));
  353.     int w2 = atoi(strtok(0, ","));
  354.  
  355.     if (ChildInfo[w1].Child->GetHandle() &&
  356.         ChildInfo[w2].Child->GetHandle())
  357.       SwapPanes(ChildInfo[w1].Child, ChildInfo[w2].Child);
  358.   }
  359. }
  360.  
  361. int
  362. sIncrN(TWindow&, void* p)
  363. {
  364.   (*(unsigned*)p)++;
  365.   return 1;
  366. }
  367.  
  368. void
  369. TMyPaneSplitter::CmForEachPane()
  370. {
  371.   unsigned n = 0;
  372.   ForEachPane(sIncrN, &n);
  373.  
  374.   char buf[10];
  375.   itoa(n, buf, 10);
  376.  
  377.   MessageBox(buf, "Number of panes:", MB_OK);
  378. }
  379.  
  380. void
  381. TMyPaneSplitter::CmSetSplitterWidth()
  382. {
  383.   char buf[10] = "";
  384.  
  385.   if (TInputDialog(GetApplication()->GetMainWindow(),
  386.                    "Set Splitter Width", "New Width:",
  387.                    buf, sizeof buf).Execute() == IDOK) {
  388.     int n = atoi(buf);
  389.     SetSplitterWidth(n);
  390.   }
  391. }
  392.  
  393. void
  394. TMyPaneSplitter::CmNumberOfPanes()
  395. {
  396.   char buf[10];
  397.   itoa(PaneCount(), buf, 10);
  398.   MessageBox(buf, "Number of panes:", MB_OK);
  399. }
  400.  
  401. void
  402. TMyPaneSplitter::CmRemoveAllPanes()
  403. {
  404.   RemoveAllPanes();
  405. }
  406.  
  407. void
  408. TMyPaneSplitter::SetupWindow()
  409. {
  410.   TPaneSplitter::SetupWindow();
  411.   SplitPane(ChildInfo[0].Child, 0, psNone);
  412. }
  413.  
  414. //----------------------------------------------------------------------------
  415.  
  416. //
  417. // class TPaneSplitterApp
  418. // ~~~~~ ~~~~~~~~~~~~~~~~
  419. class TPaneSplitterApp : public TApplication {
  420.   public:
  421.    ~TPaneSplitterApp();
  422.     void InitMainWindow();
  423. };
  424.  
  425.  
  426. TPaneSplitterApp::~TPaneSplitterApp()
  427. {
  428.   for (int i = 0; i < MaxChildren; i++) {
  429.     ChildInfo[i].Child->Destroy();
  430.     delete ChildInfo[i].Child;
  431.   }
  432. }
  433.  
  434. void
  435. TPaneSplitterApp::InitMainWindow()
  436. {
  437.   int i;
  438.   for (i = 0; i < MaxChildren; i++) {
  439.     ChildInfo[i].Child = new TMyChildWindow(0, i, 0);
  440.   }
  441.   ChildInfo[i].Child = 0;
  442.  
  443.   TDecoratedFrame* frame = new TDecoratedFrame(0, "Pane Splitters",
  444.                                          new TMyPaneSplitter(0));
  445.   frame->AssignMenu("IDM_LAYOUT");
  446.  
  447.   TControlBar* cb = new TControlBar(frame);
  448.   cb->Insert(*new TButtonGadget(IDB_VERT, CM_SPLITVERT));
  449.   cb->Insert(*new TButtonGadget(IDB_HORZ, CM_SPLITHORZ));
  450.   cb->Insert(*new TSeparatorGadget);
  451.   cb->Insert(*new TButtonGadget(IDB_SHRINK, CM_SHRINK));
  452.   cb->Insert(*new TButtonGadget(IDB_GROW, CM_GROW));
  453.   cb->Insert(*new TSeparatorGadget);
  454.   cb->Insert(*new TButtonGadget(IDB_CANCLOSE, CM_CANCLOSE));
  455.   cb->Insert(*new TButtonGadget(IDB_CANTCLOSE, CM_CANTCLOSE));
  456.   frame->Insert(*cb);
  457.  
  458.   SetMainWindow(frame);
  459. }
  460.  
  461. int
  462. OwlMain(int, char**)
  463. {
  464.   return TPaneSplitterApp().Run();
  465. }
  466.  
  467.